Turned out that this happens because of a AVFocusTensionGestureRecognizer instance.
It's the only one gesture of its kind in AVPlayerViewController view hierarchy, so you can track it down by its type and disable for now as a temporary workaround.
Post
Replies
Boosts
Views
Activity
With use of http-proxy I looked into the sequence of http requests AVPlayer makes by default for live assets (without having a AVAssetResourceLoaderDelegate set for the asset), and spotted that it makes requests with fixed delay (or it least it seems like that). Apparently renewalDate of AVAssetResourceLoadingContentInformationRequest instance should do the job, however after playing around with it I could not make it work with any values (whether it's a few seconds in future, nearing current time or set in the past) i.e. func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForRenewalOfRequestedResource renewalRequest: AVAssetResourceRenewalRequest) -> Bool method of the delegate does not get called. Another thing which drew my attention is that for live assets all manifests (master and child) have "Expires" http header set to the time of the request (that's probably what AVPlayer itself uses to deduce that the current asset is live and needs to be constantly re-requested), so ended up setting this date for the the master manifest's content information, but it didn't fix the issue either:
if let httpResonse = response as? HTTPURLResponse, let expirationValue = httpResonse.value(forHTTPHeaderField: "Expires") {
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.dateFormat = "EEE, dd MMM yyyy HH:mm:ss zzz"
contentInformationRequest.renewalDate = dateFormatter.date(from: expirationValue)
}
For some reason comprehensive documentation which would explain why it doesn't work or any sample codes with use of this property don't exist in my google. Any idea or reference I can refer to in regards to the renewalDate property?
I've finally made it work with the trick I gave in the previous message. However I had to apply the renewal date not just for master manifest request, but also for all child manifests. It's unclear why "default" playback session cannot do it itself when redirecting child manifest requests, perhaps it could not make an educated guess about type of the asset (VOD/live) without having the information from master manifest, but my implementation doesn't rely on it either:
if let httpResonse = response as? HTTPURLResponse, let expirationValue = httpResonse.value(forHTTPHeaderField: "Expires") {
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.dateFormat = "EEE, dd MMM yyyy HH:mm:ss zzz"
if let expirationDate = dateFormatter.date(from: expirationValue) {
let renewDate = max(expirationDate, Date(timeIntervalSinceNow: 8))
contentInformationRequest.renewalDate = renewDate
}
}
This line let renewDate = max(expirationDate, Date(timeIntervalSinceNow: 8)) adds 8 seconds grace period for the player to load videos. Otherwise it does not keep up with the pace of renewals, and video loads in poor quality.